//*****************************************************************************
//
// ssiflash.c - Driver for the Winbond Serial Flash on the development board.
//
// Copyright (c) 2009-2012 Texas Instruments Incorporated.  All rights reserved.
// Software License Agreement
//
// Texas Instruments (TI) is supplying this software for use solely and
// exclusively on TI's microcontroller products. The software is owned by
// TI and/or its suppliers, and is protected under applicable copyright
// laws. You may not combine this software with "viral" open-source
// software in order to form a larger program.
//
// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
// DAMAGES, FOR ANY REASON WHATSOEVER.
//
// This is part of revision 9453 of the DK-LM3S9D96 Firmware Package.
//
//*****************************************************************************
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/ssi.h"
#include "driverlib/sysctl.h"
#include "driverlib/interrupt.h"
#include "driverlib/sysctl.h"
#include "driverlib/timer.h"
#include "ssidac.h"
#include "ssi_hw.h"

#define NUM_SSI_DATA 2

unsigned int count = 0;
//*****************************************************************************
//
//! \addtogroup ssiflash_api
//! @{
//
//*****************************************************************************

//*****************************************************************************
//
// The rate of the SSI clock and derived values.
//
//*****************************************************************************
#define SSI_CLK_RATE            10000000
#define SSI_CLKS_PER_MS         (SSI_CLK_RATE / 1000)
#define STATUS_READS_PER_MS     (SSI_CLKS_PER_MS / 16)

#define AB 		0x00
#define BUF 	0x00
#define GAIN 	0x20
#define SHDN 	0x10
#define COMM 	AB|BUF|GAIN|SHDN

unsigned char first;
unsigned char second;
//*****************************************************************************
//
// Write additional data following an instruction to the serial flash.
//
// \param ucData is a pointer to data that will be sent to the device.
// \param usLen is the length of the data to send.
//
// This function writes a block of data to the serial flash device.  Typically
// this will be data to be written to a flash page.
//
// It is assumed that SSIFlashInstructionWrite() has previously been called to
// set the device chip select and send the initial instruction to the device.
//
//*****************************************************************************

void SSIDACWrite(unsigned char start, unsigned char end) {
	first = start;
	second = end;
}

unsigned long Reorder(unsigned char first, unsigned char second) {
	unsigned long var = 0;
	var = first;
	var = var << 4;
	second = second >> 4;
	var = var | second;
	var = var | 0x3000;
	return var;
}

//*****************************************************************************
//
// Finish an instruction by asserting the serial DAC chip select.
//
// This function must be called following SSIDACInstructionWrite() and,
// depending upon the instruction, SSIDACInstructionRead() to complete the
// instruction by asserting the chip select to the serial flash device.
//
//*****************************************************************************
//static void SSIDACStart(void) {
//	GPIOPinWrite(DAC_CS_BASE, DAC_CS_PIN, 0);
//
//}

//*****************************************************************************
//
// Finish an instruction by deasserting the serial flash chip select.
//
// This function must be called following SSIFlashInstructionWrite() and,
// depending upon the instruction, SSIFlashInstructionRead() to complete the
// instruction by deasserting the chip select to the serial flash device.
//
//*****************************************************************************
//static void SSIDACEnd(void) {
//	//
//	// Pull CS high to deassert it and complete the previous instruction.
//	//
//	GPIOPinWrite(DAC_CS_BASE, DAC_CS_PIN, DAC_CS_PIN);
//}

//*****************************************************************************
//
//! Initializes the SSI port and determines if the serial flash is available.
//!
//! This function must be called prior to any other function offered by the
//! serial flash driver.  It configures the SSI port to run in mode 0 at 10MHz
//! and queries the ID of the serial flash device to ensure that it is
//! available.
//!
//! \note SSI0 is shared between the serial flash and the SDCard on the
//! development board.  Two independent GPIOs are used to provide chip selects
//! for these two devices but care must be taken when using both in a single
//! application, especially during initialization of the SDCard when the SSI
//! clock rate must initially be set to 400KHz and later increased.  Since both
//! the SSI flash and SDCard drivers initialize the SSI peripheral, application
//! writers must be aware of the possible contention and ensure that they do
//! not allow the possibility of two different interrupt handlers or execution
//! threads from attempting to access both peripherals simultaneously.
//!
//! This driver assumes that the application is aware of the possibility of
//! contention and has been designed with this in mind.  Other than disabling
//! the SDCard when an attempt is made to access the serial flash, no code is
//! included here to arbitrate for ownership of the SSI peripheral.
//!
//! \return Returns \b true on success or \b false if an error is reported or
//! the expected serial flash device is not present.
//!
//*****************************************************************************
tBoolean SSIDACInit(void) {
//
// Set system clock
//
	/*SysCtlClockSet(
			SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN
					| SYSCTL_XTAL_16MHZ);*/

//
// Enable the peripherals used to drive the SDC on SSI.
//
	SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI2); //
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
	GPIOPinTypeGPIOOutput(DAC_SSI_GPIO_BASE, GPIO_PIN_5); //Chip select
//	GPIOPadConfigSet(DAC_SSI_GPIO_BASE, GPIO_PIN_5, GPIO_STRENGTH_8MA,
//			GPIO_PIN_TYPE_STD_WPU); // CS pulled High, when active, write low

//	GPIOPinWrite(DAC_SSI_GPIO_BASE, GPIO_PIN_5, GPIO_PIN_5); //Write high

	GPIOPinConfigure(GPIO_PB4_SSI2CLK);
	GPIOPinConfigure(GPIO_PB5_SSI2FSS);
	GPIOPinConfigure(GPIO_PB7_SSI2TX);

//Disable SSI base while configuring
//	SSIDisable(SSI2_BASE);
	SSIConfigSetExpClk(SSI2_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_0,
			SSI_MODE_MASTER, SysCtlClockGet() / 2, 16); //Master mode, this needs to be half supplied
														// clock speed
	GPIOPinTypeSSI(GPIO_PORTB_BASE, GPIO_PIN_4 | GPIO_PIN_7 | GPIO_PIN_5/*DAC_SSI_PINS*/); // set clk and tx as SSI
	SSIEnable(SSI2_BASE);

	unsigned int ulDACPeriod;

// Configure the DAC output timer - Timer 0
	SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER2);
	TimerConfigure(TIMER2_BASE, TIMER_CFG_PERIODIC);
	ulDACPeriod = (SysCtlClockGet()/44100);
	TimerLoadSet(TIMER2_BASE, TIMER_A, ulDACPeriod);
	IntEnable(INT_TIMER2A);

	TimerIntEnable(TIMER2_BASE, TIMER_TIMA_TIMEOUT);
	TimerEnable(TIMER2_BASE, TIMER_A);

	return (true);
}

void Timer2IntHandler(void) {
	TimerIntClear(TIMER2_BASE, TIMER_TIMA_TIMEOUT);
	if (first >= 255){
		first = 0;
	} else{
		first++;
	}
	if (second >= 255) {
		second = 0;
	} else {
		second++;
	}
	unsigned long output= 0;
	output = Reorder(first, second);

	//GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_5, 0); //Chip select
	// Put command data, wait, put data
	SSIDataPut(DAC_SSI_BASE, output);
	while (SSIBusy(SSI2_BASE)) {
	};
}

//int main(void) {
//	SSIDACInit();
//	unsigned int ulDACPeriod;
//
//// Configure the DAC output timer - Timer 2
//	SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER2);
//	TimerConfigure(TIMER2_BASE, TIMER_CFG_PERIODIC);
//	ulDACPeriod = (SysCtlClockGet());
//	TimerLoadSet(TIMER2_BASE, TIMER_A, ulDACPeriod);
//	IntEnable(INT_TIMER2A);
//
//	TimerIntEnable(TIMER2_BASE, TIMER_TIMA_TIMEOUT);
//	TimerEnable(TIMER2_BASE, TIMER_A);
//	while (1) {
//		/*if (count >= 4095){
//			count = 0;
//		} else{
//			count++;
//		}
//		//Reorder(&first, &second);
//		//GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_5, 0); //Chip select
//		// Put command data, wait, put data
//		SSIDataPut(DAC_SSI_BASE, (unsigned long) 0x3000 | (count & 0xFFF));
//		while (SSIBusy(SSI2_BASE)) {
//		};
//		SysCtlDelay(1000);*/
//
//
//	}
//}

